// ignore_for_file: prefer_function_declarations_over_variables

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math' as Math;

import 'package:amap_flutter_base/amap_flutter_base.dart';
import 'package:amap_flutter_location/amap_flutter_location.dart';
import 'package:amap_flutter_location/amap_location_option.dart';

import 'package:amap_flutter_map/amap_flutter_map.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:kmxy_base/kmxy_base.dart';
import 'package:kmxy_base/util/sp_util.dart';
import 'package:location_service_check/location_service_check.dart';

class AMapLocationUtil {
  static final AMapLocationUtil getInstance = AMapLocationUtil._internal();

  ///工厂构造函数
  factory AMapLocationUtil() => getInstance;

  ///构造函数私有化，防止被误创建
  AMapLocationUtil._internal();

  // {callbackTime: 2021-08-23 10:27:23,
  // locationTime: 2021-08-23 10:27:11,
  // locationType: 2,
  // latitude: 25.078768,
  // longitude: 102.652595,
  // accuracy: 63.0,
  // altitude: 0.0,
  // bearing: 0.0,
  // speed: 0.0,
  // country: 中国,
  // province: 云南省,
  // city: 昆明市,
  // district: 五华区,
  // street: 新明巷,
  // streetNumber: 2001号,
  // cityCode: 0871,
  // adCode: 530102,
  // address: 云南省昆明市五华区新明巷2001号靠近国家环境保护工业资源循环利用工程技术中心,
  // description: 在国家环境保护工业资源循环利用工程技术中心附近,
  // gpsAccuracyStatus: -1=卫星状态未知、0=卫星信号弱、1=卫星信号强}
  Map locationData = {};

  AMapFlutterLocation? _locationPlugin;

  late AMapLocationOption _locationOption;

  StreamSubscription<Map>? _locationListener;

  Function _mLatLngF = (Map locationData) {};

  LatLng currentLatLng = const LatLng(0, 0);

  String mAndroidKey = '';
  String mIosKey = '';

  final double _earthRadius = 6378.137;
  Dio dioMap = Dio();

  int locationCount = 0;

  Map amapTrackData = {
    'key': 'b37f4c94f05ce286d36830e15f5e6b6f',
    'sid': '931458',
    'tid': '676014304',
  };

  /// 用户隐私协议同意，请在main.dart中调用
  initPrivacy() {
    /// 高德地图合规声明，解决高德地图 errorCode : 555570
    AMapFlutterLocation.updatePrivacyAgree(true);
    AMapFlutterLocation.updatePrivacyShow(true, true);
  }

  /// 用户隐私协议同意,请在AMapWidget控件中调用
  /// AMapWidget(privacyStatement: Global.amapPrivacyStatement)
  AMapPrivacyStatement amapPrivacyStatement = const AMapPrivacyStatement(
      hasContains: true, hasShow: true, hasAgree: true);

  /**
   * 在 android/app/build.gradle 中找到以下标签加入内容
      dependencies {
      //3D地图so及jar
      implementation 'com.amap.api:3dmap:latest.integration'
      //定位功能
      implementation 'com.amap.api:location:latest.integration'
      //搜索功能
      implementation 'com.amap.api:search:latest.integration'
      }
      defaultConfig {
      ndk {
      //设置支持的SO库架构（开发者可以根据需要，选择一个或多个平台的so）
      //            abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86","x86_64"
      abiFilters 'armeabi-v7a', 'arm64-v8a'
      }
      }

   * 在 AndroidManifest.xml 中 application 标签中加入以下内容
      <!-- 配置定位Service -->
      <service android:name="com.amap.api.location.APSService"/>
      <service
           android:name="cc.cjy.kmxy_base.amap_location.LocationService"
           android:process=":remote1">
           <intent-filter>
               <action android:name="${applicationId}.LocationService" />
           </intent-filter>
       </service>
       <service
           android:name="cc.cjy.kmxy_base.amap_location.LocationHelperService"
           android:process=":remote2">
           <intent-filter>
               <action android:name="${applicationId}.LocationHelperService" />
           </intent-filter>
       </service>

   * 在 AndroidManifest.xml 中加入以下权限
      <!--访问网络-->
      <uses-permission android:name="android.permission.INTERNET" />
      <!--粗略定位-->
      <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
      <!--精确定位-->
      <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
      <!--申请调用A-GPS模块-->
      <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
      <!--用于获取运营商信息，用于支持提供运营商信息相关的接口-->
      <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
      <!--用于访问wifi网络信息，wifi信息会用于进行网络定位-->
      <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
      <!--用于获取wifi的获取权限，wifi信息会用来进行网络定位-->
      <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
      <!--用于读取手机当前的状态-->
      <uses-permission android:name="android.permission.READ_PHONE_STATE" />
      <!--用于写入缓存数据到扩展存储卡-->
      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
      <!-- 后台唤醒定位需要的权限 -->
      <uses-permission android:name="android.permission.WAKE_LOCK" />
      <!-- NotiService$NotiInnerService需要的权限-->
      <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />

   * 在 ios/Runner/Info.plist 中 dict 标签下加入以下内容
      <key>NSLocationAlwaysUsageDescription</key>
      <string>请允许APP使用定位，用于地图</string>
      <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
      <string>请允许APP使用定位，用于地图</string>
      <key>NSLocationWhenInUseUsageDescription</key>
      <string>请允许APP使用定位，用于地图</string>

   * 如果遇到开发问题，请到高德地图flutter官网查看
      https://developer.amap.com/api/flutter/summary
   */

  /// 初始化，请在进入APP的时候调用，初始前请加入上面的配置
  initLocation(String androidKey, String iosKey) {
    if (_locationListener != null) return;
    mAndroidKey = androidKey;
    mIosKey = iosKey;
    AMapFlutterLocation.setApiKey(mAndroidKey, mIosKey);
    _locationPlugin = AMapFlutterLocation();

    ///注册定位结果监听
    if (Platform.isAndroid) {
      KmxyBase.setMethodCallHandler((MethodCall methodCall) async {
        if (methodCall.method == 'locationServiceCallback') {
          if (methodCall.arguments != null) {
            Map locationServiceData = jsonDecode(methodCall.arguments);
            locationServiceData['latitude'] = locationServiceData['lat'];
            locationServiceData['longitude'] = locationServiceData['lon'];
            await locationListener(locationServiceData);
          }
        }
      });
    } else {
      // // ios 本地定位
      // KmxyBase.setMethodCallHandler((MethodCall methodCall) async {
      //   if (methodCall.method == 'locationServiceCallback') {
      //     print(methodCall.arguments);
      //     Map locationServiceData = jsonDecode(methodCall.arguments);
      //     locationServiceData['latitude'] = locationServiceData['latitude'];
      //     locationServiceData['longitude'] = locationServiceData['longitude'];
      //   }
      // });
      _locationListener =
          _locationPlugin?.onLocationChanged().listen((Map result) async {
        await locationListener(result);
      });
    }
  }

  /// 定位数据监听
  locationListener(Map result) async {
    locationCount++;
    result['locationCount'] = locationCount;
    locationData = result;
    locationData['locationTypeText'] = locationTypeText(
        int.parse((locationData['locationType'] ?? 0).toString()));
    if (locationData.isNotEmpty &&
        locationData['latitude'] != null &&
        locationData['longitude'] != null) {
      locationData['latitude'] =
          double.parse(locationData['latitude'].toString()).toStringAsFixed(6);
      locationData['longitude'] =
          double.parse(locationData['longitude'].toString()).toStringAsFixed(6);
      currentLatLng = LatLng(double.parse(locationData['latitude'].toString()),
          double.parse(locationData['longitude'].toString()));
      if (locationData['address'].toString() == '[]') {
        locationData['address'] = '';
      }
      if (locationData['address'] == null ||
          locationData['address'].toString().isEmpty) {
        // webApi获取定位地址
        await getAddress();
      }
      if (locationData['country'] == '中国') {
        if (!_isStartPatrol && _initStartLatLngFinish) {
          EasyLoading.dismiss();
        }
        await _initStartLatLng();
        await _startPatrol();
      }
      _mLatLngF(locationData);
    }
  }

  /// 获取高德地图定位控制类
  AMapFlutterLocation? get aMapFlutterLocation => _locationPlugin;

  /// 获取高德地图定位配置类
  AMapLocationOption get aMapLocationOption => _locationOption;

  /// 坐标转地理位置
  getAddress() async {
    var respone = await dioMap.get(
        'https://restapi.amap.com/v3/geocode/regeo?location=${locationData['longitude']},${locationData['latitude']}&key=b37f4c94f05ce286d36830e15f5e6b6f');
    if (respone.data['info'] == 'OK') {
      locationData['address'] = respone.data['regeocode']['formatted_address'];
      locationData['country'] =
          respone.data['regeocode']['addressComponent']['country'];
      locationData['province'] =
          respone.data['regeocode']['addressComponent']['province'];
      locationData['city'] =
          respone.data['regeocode']['addressComponent']['city'];
      locationData['district'] =
          respone.data['regeocode']['addressComponent']['district'];
      locationData['district'] =
          respone.data['regeocode']['addressComponent']['district'];
      locationData['street'] = respone.data['regeocode']['addressComponent']
          ['streetNumber']['street'];
      locationData['streetNumber'] = respone.data['regeocode']
          ['addressComponent']['streetNumber']['number'];
      locationData['cityCode'] =
          respone.data['regeocode']['addressComponent']['citycode'];
      locationData['adCode'] =
          respone.data['regeocode']['addressComponent']['adcode'];
    }
  }

  /// 坐标转地理位置
  Future<String> getAddressLatLng(LatLng latLng) async {
    var respone = await dioMap.get(
        'https://restapi.amap.com/v3/geocode/regeo?location=${latLng.longitude},${latLng.latitude}&key=b37f4c94f05ce286d36830e15f5e6b6f');
    if (respone.data['info'] == 'OK') {
      return respone.data['regeocode']['formatted_address'];
    }
    return '';
  }

  /// 坐标转地理位置全数据
  Future<Map> getAddressAllData(LatLng latLng) async {
    var respone = await dioMap.get(
        'https://restapi.amap.com/v3/geocode/regeo?location=${latLng.longitude},${latLng.latitude}&key=b37f4c94f05ce286d36830e15f5e6b6f&radius=1000&extensions=all&roadlevel=0');
    if (respone.data['info'] == 'OK') {
      return respone.data['regeocode'];
    }
    return {};
  }

  ///设置定位参数
  _setLocationOption() {
    _locationOption = AMapLocationOption();

    ///是否单次定位
    _locationOption.onceLocation = false;

    ///是否需要返回逆地理信息
    _locationOption.needAddress = true;

    ///逆地理信息的语言类型
    _locationOption.geoLanguage = GeoLanguage.DEFAULT;

    _locationOption.desiredLocationAccuracyAuthorizationMode =
        AMapLocationAccuracyAuthorizationMode.FullAccuracy;

    _locationOption.fullAccuracyPurposeKey = "AMapLocationScene";

    ///设置Android端连续定位的定位间隔
    _locationOption.locationInterval = 2000;

    ///设置Android端的定位模式<br>
    ///可选值：<br>
    ///<li>[AMapLocationMode.Battery_Saving]</li>
    ///<li>[AMapLocationMode.Device_Sensors]</li>
    ///<li>[AMapLocationMode.Hight_Accuracy]</li>
    _locationOption.locationMode = AMapLocationMode.Hight_Accuracy;

    ///设置iOS端的定位最小更新距离<br>
    _locationOption.distanceFilter = -1;

    ///设置iOS端期望的定位精度
    /// 可选值：<br>
    /// <li>[DesiredAccuracy.Best] 最高精度</li>
    /// <li>[DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度 </li>
    /// <li>[DesiredAccuracy.NearestTenMeters] 10米 </li>
    /// <li>[DesiredAccuracy.Kilometer] 1000米</li>
    /// <li>[DesiredAccuracy.ThreeKilometers] 3000米</li>
    _locationOption.desiredAccuracy = DesiredAccuracy.Best;

    ///设置iOS端是否允许系统暂停定位
    _locationOption.pausesLocationUpdatesAutomatically = false;

    ///将定位参数设置给定位插件
    _locationPlugin?.setLocationOption(_locationOption);
  }

  /// 更新地图显示位置
  updateMapPosition(LatLng latLng, AMapController controller,
      {double zoom = 14}) {
    CameraUpdate update = CameraUpdate.newCameraPosition(
      CameraPosition(
        //中心点
        target: latLng,
        //缩放级别
        zoom: zoom,
      ),
    );
    controller.moveCamera(update);
  }

  /// 添加多边形
  Polygon addPolygons(List<LatLng> poi,
      {int strokeColor = 0xCCC4E0F0,
      int fillColor = 0xC4E0F0CC,
      double width = 10}) {
    return Polygon(
      strokeColor: Color(strokeColor),
      fillColor: Color(fillColor),
      strokeWidth: width,
      points: [...poi],
    );
  }

  /// 添加路径
  Polyline addPolyLine(List<LatLng> poi,
      {String? iconPath, Color? color, double width = 10}) {
    return Polyline(
      width: width,
      color: color ?? const Color(0xCCC4E0F0),
      customTexture:
          iconPath == null ? null : BitmapDescriptor.fromIconPath(iconPath),
      joinType: JoinType.round,
      points: [...poi],
    );
  }

  ///  添加路径-网路图片
  Polyline addPolyLineNetworkImage(List<LatLng> poi, Uint8List uint8list,
      {Color? color, double width = 10}) {
    return Polyline(
      width: width,
      color: color ?? const Color(0xCCC4E0F0),
      customTexture: BitmapDescriptor.fromBytes(uint8list),
      joinType: JoinType.round,
      points: [...poi],
    );
  }

  /// 添加标记点
  Marker addMarker(LatLng markerPosition, String iconPath,
      {ArgumentCallback<String>? onTap}) {
    return Marker(
        position: markerPosition,
        icon: BitmapDescriptor.fromIconPath(iconPath),
        infoWindowEnable: false,
        onTap: onTap);
  }

  /// 添加标记点
  Marker addMarkerInfoWindow(LatLng markerPosition, String iconPath,
      {ArgumentCallback<String>? onTap,
      infoWindowEnable = false,
      infoWindow = InfoWindow.noText}) {
    return Marker(
        position: markerPosition,
        icon: BitmapDescriptor.fromIconPath(iconPath),
        infoWindowEnable: infoWindowEnable,
        infoWindow: infoWindow,
        onTap: onTap);
  }

  /// 添加标记点-可控制图标大小
  Future<Marker> addMarkerAssetImage(LatLng markerPosition, String iconPath,
      {double devicePixelRatio = 1, ArgumentCallback<String>? onTap}) async {
    return Marker(
        position: markerPosition,
        icon: await BitmapDescriptor.fromAssetImage(
            ImageConfiguration(devicePixelRatio: devicePixelRatio), iconPath,
            mipmaps: false),
        infoWindowEnable: false,
        onTap: onTap);
  }

  /// 添加标记点-网路图片
  Marker addMarkerNetworkImage(LatLng markerPosition, Uint8List uint8list,
      {ArgumentCallback<String>? onTap}) {
    return Marker(
        position: markerPosition,
        icon: BitmapDescriptor.fromBytes(uint8list),
        infoWindowEnable: false,
        onTap: onTap);
  }

  /// 开始定位
  startLocation() {
    _setLocationOption();
    locationCount = 0;
    _locationPlugin?.startLocation();
    if (Platform.isAndroid) {
      KmxyBase.startLocationService();
    }
  }

  /// 停止定位
  stopLocation() {
    _locationPlugin?.stopLocation();
    if (Platform.isAndroid) {
      KmxyBase.stopLocationService();
    }
    endPatrol();
  }

  /// 获取两点之间的距离（米）
  double getDistance(LatLng sLatLng, LatLng eLatLng) {
    double radLat1 = _rad(sLatLng.latitude);
    double radLat2 = _rad(eLatLng.latitude);
    double a = radLat1 - radLat2;
    double b = _rad(sLatLng.longitude) - _rad(eLatLng.longitude);
    double s = 2 *
        Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
            Math.cos(radLat1) *
                Math.cos(radLat2) *
                Math.pow(Math.sin(b / 2), 2)));
    s = s * _earthRadius;
    s = (s * 10000).round() / 10000;
    s = s * 1000;
    return s;
  }

  double _rad(double d) {
    return d * Math.pi / 180.0;
  }

  /// 销毁定位
  destroyLocation() {
    // 移除定位监听
    _locationListener?.cancel();

    // 销毁定位
    _locationPlugin?.destroy();
  }

  /// 判断是否开启GPS，true是开启
  Future<bool> isOpenGps() async {
    return await LocationServiceCheck.checkLocationIsOpen;
  }

  /// ----------------巡查相关----------------

  /// 巡查坐标列表
  final List<LatLng> latLngList = [];

  /// 巡查坐标列表，用于高德猎鹰纠偏
  final List aMapLatLngList = [];

  /// 临时坐标列表
  final List<LatLng> _temp3LatLngList = [];

  // 是否开始巡查
  bool _isStartPatrol = false;
  // 初始化巡查开始坐标点
  bool _initStartLatLngFinish = true;

  // ignore: non_constant_identifier_names
  final String SP_LATLNG_LIST = 'SP_LATLNG_LIST';
  final String SP_LATLNG_LIST_DKRW = 'SP_LATLNG_LIST_DKRW';

  Function _mPatrolF = () {};

  Function _mInitStartLatLngFinishF = (Map locationData) {};

  bool get isStartPatrol => _isStartPatrol;

  /// 设置巡查更新路径的监听
  setPatrolListener(Function() patrolF) {
    _mPatrolF = patrolF;
  }

  /// 设置位置监听
  setLatLngListener(Function(Map locationData) latLngF) {
    _mLatLngF = latLngF;
  }

  /// 设置巡查开始点处理完成监听
  setInitStartLatLngFinishListener(Function() initStartLatLngFinishF) {
    _mInitStartLatLngFinishF = initStartLatLngFinishF;
  }

  /// 开始巡查
  startPatrol() {
    _initStartLatLngFinish = false;
  }

  /// 结束巡查
  Future endPatrol() async {
    _initStartLatLngFinish = true;
    _isStartPatrol = false;
    // 本地存储巡查坐标数据
    if (latLngList.isNotEmpty) {
      await SpUtil.setString(SP_LATLNG_LIST, jsonEncode(latLngList));
      await SpUtil.setString(SP_LATLNG_LIST_DKRW, jsonEncode(latLngList));
    }
    _temp3LatLngList.clear();
    latLngList.clear();
    aMapLatLngList.clear();
  }

  /// 开始巡查
  _startPatrol() async {
    if (!_isStartPatrol) return;
    // 剔除重复坐标
    if (latLngList.length > 1) {
      // 获取列表中最后一个坐标点
      double listLast1Latitude =
          double.parse(latLngList.last.latitude.toStringAsFixed(6));
      double listLast1Longitude =
          double.parse(latLngList.last.longitude.toStringAsFixed(6));
      // 获取列表中倒数第二个坐标点
      int index = latLngList.length - 2;
      double listLast2Latitude =
          double.parse(latLngList[index].latitude.toStringAsFixed(6));
      double listLast2Longitude =
          double.parse(latLngList[index].longitude.toStringAsFixed(6));
      // 重复坐标点比对
      if (listLast1Latitude == listLast2Latitude &&
          listLast1Longitude == listLast2Longitude) {
        latLngList.removeLast();
      }
    }
    if (_temp3LatLngList.length == 3) {
      // 处理坐标
      // 第一个坐标和第二个坐标比对
      if ((_temp3LatLngList[0].longitude - _temp3LatLngList[1].longitude)
                  .abs() >
              0.001 ||
          (_temp3LatLngList[0].latitude - _temp3LatLngList[1].latitude).abs() >
              0.0005) {
        // 异常坐标
        // 第一个坐标和第三个坐标比对
        if ((_temp3LatLngList[0].longitude - _temp3LatLngList[2].longitude)
                    .abs() >
                0.001 ||
            (_temp3LatLngList[0].latitude - _temp3LatLngList[2].latitude)
                    .abs() >
                0.0005) {
          // 异常坐标
          _temp3LatLngList.removeAt(0);
          return;
        } else {
          _temp3LatLngList.removeAt(1);
          return;
        }
      } else {
        // 第二个坐标和第三个坐标比对
        if ((_temp3LatLngList[1].longitude - _temp3LatLngList[2].longitude)
                    .abs() >
                0.001 ||
            (_temp3LatLngList[1].latitude - _temp3LatLngList[2].latitude)
                    .abs() >
                0.0005) {
          // 异常坐标
          _temp3LatLngList.removeAt(2);
          return;
        }
      }
      // 去平均值坐标点
      double latitude = (_temp3LatLngList[0].latitude +
              _temp3LatLngList[1].latitude +
              _temp3LatLngList[2].latitude) /
          3;
      latitude = double.parse(latitude.toStringAsFixed(6));
      double longitude = (_temp3LatLngList[0].longitude +
              _temp3LatLngList[1].longitude +
              _temp3LatLngList[2].longitude) /
          3;
      longitude = double.parse(longitude.toStringAsFixed(6));
      // 获取列表中最后一个坐标点
      double listLast1Latitude =
          double.parse(latLngList.last.latitude.toStringAsFixed(6));
      double listLast1Longitude =
          double.parse(latLngList.last.longitude.toStringAsFixed(6));
      // 重复坐标点比对
      if (listLast1Latitude == latitude && listLast1Longitude == longitude) {
        _temp3LatLngList.clear();
        return;
      }
      // 相邻三个坐标比对，判断第二个是否有飞坐标
      // 最少有两个坐标
      if (latLngList.length > 1) {
        // 获取列表中倒数第二个坐标点
        int index = latLngList.length - 2;
        double listLast2Latitude =
            double.parse(latLngList[index].latitude.toStringAsFixed(6));
        double listLast2Longitude =
            double.parse(latLngList[index].longitude.toStringAsFixed(6));
        // 倒数第二个坐标和现在获取的坐标，是否满足正常范围
        if ((listLast2Latitude - latitude).abs() <= 0.001 &&
            (listLast2Longitude - longitude).abs() <= 0.0005) {
          if ((listLast1Latitude - latitude).abs() > 0.001 &&
              (listLast1Longitude - longitude).abs() > 0.0005) {
            // 第二个是飞坐标,列表最后一个坐标是飞坐标
            latLngList.removeLast();
          }
        }
      }
      // 巡查坐标点获取确定成功
      LatLng latLng = LatLng(latitude, longitude);
      latLngList.add(latLng);

      aMapLatLngList.add({
        'location': '$longitude,$latitude',
        'locatetime': DateTime.now().millisecondsSinceEpoch
      });
      // 在地图上画出巡查轨迹-回调
      _mPatrolF();
      _temp3LatLngList.clear();
      // 本地存储巡查坐标数据
      if (latLngList.isNotEmpty) {
        await SpUtil.setString(SP_LATLNG_LIST, jsonEncode(latLngList));
        await SpUtil.setString(SP_LATLNG_LIST_DKRW, jsonEncode(latLngList));
      }
    } else {
      // 添加3次开始坐标，比对
      _temp3LatLngList.add(currentLatLng);
    }
  }

  // 零时收集3次坐标的次数
  int countTemp3LatLngList = 0;

  /// 初始化开始坐标点
  _initStartLatLng() async {
    if (_initStartLatLngFinish) return;
    EasyLoading.show(status: '数据处理中');
    // 确定开始位置
    if (latLngList.isEmpty) {
      // 新的巡查
      if (_temp3LatLngList.length == 3) {
        // 由于会出现卡死在获取初始坐标的情况下，所以判断获取初始点的坐标进入了几次，
        // 大于3次就清空临时坐标，全部重新获取
        if (countTemp3LatLngList > 3) {
          _temp3LatLngList.clear();
          countTemp3LatLngList = 0;
          return;
        }
        countTemp3LatLngList++;
        // 处理开始坐标
        // 第一个坐标和第二个坐标比对
        if ((_temp3LatLngList[0].longitude - _temp3LatLngList[1].longitude)
                    .abs() >
                0.001 ||
            (_temp3LatLngList[0].latitude - _temp3LatLngList[1].latitude)
                    .abs() >
                0.0005) {
          // 异常坐标
          // 第一个坐标和第三个坐标比对
          if ((_temp3LatLngList[0].longitude - _temp3LatLngList[2].longitude)
                      .abs() >
                  0.001 ||
              (_temp3LatLngList[0].latitude - _temp3LatLngList[2].latitude)
                      .abs() >
                  0.0005) {
            // 异常坐标
            _temp3LatLngList.removeAt(0);
            return;
          } else {
            _temp3LatLngList.removeAt(1);
            return;
          }
        } else {
          // 第二个坐标和第三个坐标比对
          if ((_temp3LatLngList[1].longitude - _temp3LatLngList[2].longitude)
                      .abs() >
                  0.001 ||
              (_temp3LatLngList[1].latitude - _temp3LatLngList[2].latitude)
                      .abs() >
                  0.0005) {
            // 异常坐标
            _temp3LatLngList.removeAt(2);
            return;
          }
        }
        // 去平均值坐标点
        double startLatitude = (_temp3LatLngList[0].latitude +
                _temp3LatLngList[1].latitude +
                _temp3LatLngList[2].latitude) /
            3;
        startLatitude = double.parse(startLatitude.toStringAsFixed(6));
        double startLongitude = (_temp3LatLngList[0].longitude +
                _temp3LatLngList[1].longitude +
                _temp3LatLngList[2].longitude) /
            3;
        startLongitude = double.parse(startLongitude.toStringAsFixed(6));
        LatLng latLng = LatLng(startLatitude, startLongitude);
        // 初始化开始点完成
        _initStartLatLngFinish = true;
        // 将开始坐标点加入坐标列表
        latLngList.add(latLng);
        aMapLatLngList.add({
          'location': '$startLongitude,$startLatitude',
          'locatetime': DateTime.now().millisecondsSinceEpoch
        });
        // 在地图上画出开始点-回调
        _mInitStartLatLngFinishF();
        _temp3LatLngList.clear();
        countTemp3LatLngList = 0;
        _isStartPatrol = true;
        // 本地存储巡查坐标数据
        if (latLngList.isNotEmpty) {
          await SpUtil.setString(SP_LATLNG_LIST, jsonEncode(latLngList));
          await SpUtil.setString(SP_LATLNG_LIST_DKRW, jsonEncode(latLngList));
        }
        EasyLoading.dismiss();
      } else {
        // 添加3次开始坐标，比对
        _temp3LatLngList.add(currentLatLng);
      }
    } else {
      // 历史巡查
      // 初始化开始点完成
      _initStartLatLngFinish = true;
      // 在地图上画出开始点-回调
      // 在地图上画出巡查轨迹-回调
      _mInitStartLatLngFinishF();
      _temp3LatLngList.clear();
      countTemp3LatLngList = 0;
      _isStartPatrol = true;
      EasyLoading.dismiss();
    }
  }

  /// 获取当前定位类型
  /// 0-定位失败-请通过AMapLocation.getErrorCode()方法获取错误码，并参考错误码对照表进行问题排查。
  /// 1-GPS定位结果-通过设备GPS定位模块返回的定位结果，精度较高，在10米－100米左右
  /// 2-前次定位结果-网络定位请求低于1秒、或两次定位之间设备位置变化非常小时返回，设备位移通过传感器感知。
  /// 4-缓存定位结果-返回一段时间前设备在同样的位置缓存下来的网络定位结果
  /// 5-Wifi定位结果-属于网络定位，定位精度相对基站定位会更好，定位精度较高，在5米－200米之间。
  /// 6-基站定位结果-纯粹依赖移动、联通、电信等移动网络定位，定位精度在500米-5000米之间。
  /// 8-离线定位结果
  /// 9-最后位置缓存
  /// 11-模糊定位结果-模糊定位权限，当用户设置应用定位权限为“大致位置”时，返回用户大致位置
  String locationTypeText(int num) {
    switch (num) {
      case 0:
        return '定位失败';
      case 1:
        return 'GPS定位';
      case 2:
        return '上次定位';
      case 4:
        return '缓存定位';
      case 5:
        return 'Wifi定位';
      case 6:
        return '基站定位';
      case 8:
        return '离线定位';
      case 9:
        return '最后定位';
      case 11:
        return '模糊定位';
    }
    return '';
  }

  /// 使用gps定位
  setGPSLocation() {
    _locationOption.locationMode = AMapLocationMode.Device_Sensors;
    _locationPlugin?.setLocationOption(_locationOption);
  }

  /// 使用网络定位
  setNetLocation() {
    _locationOption.locationMode = AMapLocationMode.Hight_Accuracy;
    _locationPlugin?.setLocationOption(_locationOption);
  }

  List osXxxx = [
    {"location": "102.655233,25.067078", "locatetime": 1682471345967},
    {"location": "102.655268,25.067061", "locatetime": 1682471346971},
    {"location": "102.655093,25.067155", "locatetime": 1682471347974},
    {"location": "102.654963,25.067129", "locatetime": 1682471348977},
    {"location": "102.654824,25.066980", "locatetime": 1682471349981},
    {"location": "102.654837,25.066976", "locatetime": 1682471350985},
    {"location": "102.654615,25.067066", "locatetime": 1682471351989},
    {"location": "102.654533,25.067086", "locatetime": 1682471352992},
    {"location": "102.654492,25.067078", "locatetime": 1682471353997},
    {"location": "102.654458,25.067070", "locatetime": 1682471355001},
    {"location": "102.654426,25.067061", "locatetime": 1682471356009},
    {"location": "102.654396,25.067107", "locatetime": 1682471357012},
    {"location": "102.654365,25.067134", "locatetime": 1682471358016},
    {"location": "102.654382,25.067111", "locatetime": 1682471359019},
    {"location": "102.654416,25.067077", "locatetime": 1682471360024},
    {"location": "102.654428,25.067058", "locatetime": 1682471361028},
    {"location": "102.654417,25.067055", "locatetime": 1682471362032},
    {"location": "102.654364,25.067053", "locatetime": 1682471363037},
    {"location": "102.654279,25.067045", "locatetime": 1682471364041},
    {"location": "102.654222,25.067032", "locatetime": 1682471365047},
    {"location": "102.654198,25.067025", "locatetime": 1682471366051},
    {"location": "102.654186,25.067022", "locatetime": 1682471367055},
    {"location": "102.654180,25.067021", "locatetime": 1682471368062},
    {"location": "102.654177,25.067021", "locatetime": 1682471369069},
    {"location": "102.654176,25.067021", "locatetime": 1682471370073},
    {"location": "102.654173,25.067018", "locatetime": 1682471371077},
    {"location": "102.654171,25.067013", "locatetime": 1682471372082},
    {"location": "102.654166,25.067009", "locatetime": 1682471373086},
    {"location": "102.654163,25.067004", "locatetime": 1682471374090},
    {"location": "102.654168,25.067000", "locatetime": 1682471375097},
    {"location": "102.654169,25.067001", "locatetime": 1682471376104},
    {"location": "102.654809,25.066859", "locatetime": 1682471377109},
    {"location": "102.653905,25.068153", "locatetime": 1682471378114},
    {"location": "102.653700,25.068060", "locatetime": 1682471379120},
    {"location": "102.653455,25.067965", "locatetime": 1682471380128},
    {"location": "102.653291,25.067968", "locatetime": 1682471381135},
    {"location": "102.653383,25.067982", "locatetime": 1682471382144},
    {"location": "102.653482,25.067951", "locatetime": 1682471383152},
    {"location": "102.653503,25.067994", "locatetime": 1682471384158},
    {"location": "102.653518,25.068073", "locatetime": 1682471385166},
    {"location": "102.653589,25.068149", "locatetime": 1682471386172},
    {"location": "102.653668,25.068266", "locatetime": 1682471387176},
    {"location": "102.653725,25.068377", "locatetime": 1682471388181},
    {"location": "102.653801,25.068539", "locatetime": 1682471389185},
    {"location": "102.653855,25.068636", "locatetime": 1682471390189},
    {"location": "102.653791,25.068735", "locatetime": 1682471391196},
    {"location": "102.653785,25.068834", "locatetime": 1682471392204},
    {"location": "102.653709,25.068785", "locatetime": 1682471393210},
    {"location": "102.653613,25.068735", "locatetime": 1682471394215},
    {"location": "102.653420,25.068821", "locatetime": 1682471395223},
    {"location": "102.653116,25.068995", "locatetime": 1682471396228},
    {"location": "102.652908,25.069094", "locatetime": 1682471397233},
    {"location": "102.652654,25.069129", "locatetime": 1682471398238},
    {"location": "102.652429,25.069184", "locatetime": 1682471399243},
    {"location": "102.652427,25.069104", "locatetime": 1682471400246},
    {"location": "102.652405,25.068999", "locatetime": 1682471401251},
    {"location": "102.652353,25.068869", "locatetime": 1682471402258},
    {"location": "102.652331,25.068813", "locatetime": 1682471403263},
    {"location": "102.652167,25.069008", "locatetime": 1682471404267},
    {"location": "102.651984,25.069426", "locatetime": 1682471405270},
    {"location": "102.651853,25.069843", "locatetime": 1682471406279},
    {"location": "102.651798,25.070102", "locatetime": 1682471407282},
    {"location": "102.651614,25.070299", "locatetime": 1682471408288},
    {"location": "102.651359,25.070516", "locatetime": 1682471409292},
    {"location": "102.650928,25.070919", "locatetime": 1682471410300},
    {"location": "102.650908,25.071359", "locatetime": 1682471411306},
    {"location": "102.650902,25.071735", "locatetime": 1682471412309},
    {"location": "102.650962,25.072115", "locatetime": 1682471413313},
    {"location": "102.650995,25.072359", "locatetime": 1682471414318},
    {"location": "102.651072,25.072545", "locatetime": 1682471415324},
    {"location": "102.651150,25.072682", "locatetime": 1682471416332},
    {"location": "102.651219,25.072824", "locatetime": 1682471417339},
    {"location": "102.651307,25.073004", "locatetime": 1682471418345},
    {"location": "102.651449,25.073183", "locatetime": 1682471419352},
    {"location": "102.651597,25.073353", "locatetime": 1682471420356},
    {"location": "102.651681,25.073527", "locatetime": 1682471421360},
    {"location": "102.651773,25.073758", "locatetime": 1682471422367},
    {"location": "102.651825,25.074048", "locatetime": 1682471423376},
    {"location": "102.651805,25.074164", "locatetime": 1682471424379},
    {"location": "102.651798,25.074322", "locatetime": 1682471425385},
    {"location": "102.651838,25.074522", "locatetime": 1682471426392},
    {"location": "102.651848,25.074681", "locatetime": 1682471427398},
    {"location": "102.651886,25.074834", "locatetime": 1682471428402},
    {"location": "102.651968,25.074983", "locatetime": 1682471429406},
    {"location": "102.652047,25.075116", "locatetime": 1682471430412},
    {"location": "102.652085,25.075254", "locatetime": 1682471431417},
    {"location": "102.652145,25.075482", "locatetime": 1682471432421},
    {"location": "102.652339,25.075712", "locatetime": 1682471433425},
    {"location": "102.652664,25.076009", "locatetime": 1682471434436},
    {"location": "102.653242,25.076379", "locatetime": 1682471435443},
    {"location": "102.653481,25.076595", "locatetime": 1682471436448},
    {"location": "102.653574,25.076744", "locatetime": 1682471437453},
    {"location": "102.653622,25.076842", "locatetime": 1682471438462},
    {"location": "102.653634,25.076955", "locatetime": 1682471439468},
    {"location": "102.653613,25.077044", "locatetime": 1682471442746},
    {"location": "102.653604,25.077064", "locatetime": 1682471443753},
    {"location": "102.653576,25.077133", "locatetime": 1682471444760},
    {"location": "102.653570,25.077225", "locatetime": 1682471445767},
    {"location": "102.653493,25.077223", "locatetime": 1682471446772},
    {"location": "102.653401,25.077222", "locatetime": 1682471447776},
    {"location": "102.653321,25.077268", "locatetime": 1682471448780},
    {"location": "102.653270,25.077328", "locatetime": 1682471645336},
    {"location": "102.653270,25.077368", "locatetime": 1682471650123},
    {"location": "102.653260,25.077389", "locatetime": 1682471651130},
    {"location": "102.653265,25.077449", "locatetime": 1682471652136},
    {"location": "102.653286,25.077546", "locatetime": 1682471653141},
    {"location": "102.653267,25.077555", "locatetime": 1682471654149},
    {"location": "102.653291,25.077624", "locatetime": 1682471655155},
    {"location": "102.653297,25.077671", "locatetime": 1682471656160},
    {"location": "102.653309,25.077648", "locatetime": 1682471657166},
    {"location": "102.653325,25.077619", "locatetime": 1682471658172},
    {"location": "102.653248,25.077593", "locatetime": 1682471659176},
    {"location": "102.653180,25.077560", "locatetime": 1682471660181},
    {"location": "102.653131,25.077527", "locatetime": 1682471661183},
    {"location": "102.653098,25.077518", "locatetime": 1682471662189},
    {"location": "102.653093,25.077518", "locatetime": 1682471663195},
    {"location": "102.653054,25.077502", "locatetime": 1682471664200},
    {"location": "102.652996,25.077510", "locatetime": 1682471665206},
    {"location": "102.652927,25.077529", "locatetime": 1682471666209},
    {"location": "102.652863,25.077558", "locatetime": 1682471667215},
    {"location": "102.652812,25.077595", "locatetime": 1682471668219},
    {"location": "102.652753,25.077655", "locatetime": 1682471669224},
    {"location": "102.652695,25.077715", "locatetime": 1682471670232},
    {"location": "102.652646,25.077747", "locatetime": 1682471671239},
    {"location": "102.652604,25.077772", "locatetime": 1682471672242},
    {"location": "102.652570,25.077796", "locatetime": 1682471673244},
    {"location": "102.652571,25.077827", "locatetime": 1682471674247},
    {"location": "102.652601,25.077857", "locatetime": 1682471675250},
    {"location": "102.652616,25.077883", "locatetime": 1682471676259},
    {"location": "102.652626,25.077917", "locatetime": 1682471677265},
    {"location": "102.652637,25.077927", "locatetime": 1682471678275},
    {"location": "102.652662,25.077916", "locatetime": 1682471679279},
    {"location": "102.652689,25.077940", "locatetime": 1682471680284},
    {"location": "102.652715,25.077959", "locatetime": 1682471681291},
    {"location": "102.652740,25.077976", "locatetime": 1682471682296},
    {"location": "102.652758,25.078006", "locatetime": 1682471683302},
    {"location": "102.652765,25.078035", "locatetime": 1682471684308},
    {"location": "102.652768,25.078056", "locatetime": 1682471685313},
    {"location": "102.652775,25.078044", "locatetime": 1682471686317},
    {"location": "102.652796,25.078047", "locatetime": 1682471687321}
  ];

  /// 上传高德猎鹰轨迹定位
  Future<List> upAmapLatLngList(List list, String? correction) async {
    List makeDataList = [];
    // int i = 0;
    // for (Map item in list) {
    //   item['lgtd'] = double.parse(item['lgtd']).toStringAsFixed(6);
    //   item['lttd'] = double.parse(item['lttd']).toStringAsFixed(6);
    //   makeDataList.add({
    //     'location': '${item['lgtd']},${item['lttd']}',
    //     'locatetime': DateTime.now().millisecondsSinceEpoch,
    //   });
    //   await Future.delayed(Duration(milliseconds: 1000), () {});
    //   i++;
    // }
    makeDataList.addAll(list);
    List tempList = [];
    if (makeDataList.length > 100) {
      int splitCount = 0;
      if (makeDataList.length % 100 == 0) {
        splitCount = makeDataList.length ~/ 100;
      } else {
        splitCount = makeDataList.length ~/ 100 + 1;
      }
      for (int i = 0; i < splitCount; i++) {
        int startIndex = i * 100;
        int endIndex = startIndex + 100;
        if (endIndex > makeDataList.length) {
          endIndex = makeDataList.length;
        }
        tempList.add(makeDataList.sublist(startIndex, endIndex));
      }
    } else {
      tempList.add(makeDataList);
    }
    List amapTrackList = [];
    for (List tempListN in tempList) {
      String? trid = await amapCreateTrack();
      if (trid == null) {
        return [];
      }
      String? data = await amapUpTrack(trid, tempListN);
      if (data == null) {
        amapDelTrack(trid);
        return [];
      }
      List? list = await amapGetTrack(trid, correction);
      if (list == null) {
        amapDelTrack(trid);
        return [];
      }
      amapDelTrack(trid);
      amapTrackList.addAll(list);
    }
    return amapTrackList;
  }

  // 创建猎鹰轨迹
  Future<String?> amapCreateTrack() async {
    // 创建猎鹰轨迹
    var respone = await dioMap.post('https://tsapi.amap.com/v1/track/trace/add',
        options: Options(
            headers: {'content-type': 'application/x-www-form-urlencoded'},
            method: 'POST'),
        data: {
          'key': amapTrackData['key'],
          'sid': amapTrackData['sid'],
          'tid': amapTrackData['tid'],
        });
    if (respone.data['errcode'] == 10000) {
      return respone.data['data']['trid'].toString();
    }
    return null;
  }

  // 上传轨迹，每次只接收100个坐标
  Future<String?> amapUpTrack(String trid, List points) async {
    var respone = await dioMap.post(
        'https://tsapi.amap.com/v1/track/point/upload',
        options: Options(
            headers: {'content-type': 'application/x-www-form-urlencoded'},
            method: 'POST'),
        data: {
          'key': amapTrackData['key'],
          'sid': amapTrackData['sid'],
          'tid': amapTrackData['tid'],
          'trid': trid,
          'points': jsonEncode(points)
        });
    if (respone.data['errcode'] == 10000) {
      return '成功';
    }
    return null;
  }

  // 获取纠偏轨迹
  Future<List?> amapGetTrack(String trid, String? correction) async {
    var respone = await dioMap.post(
        'https://tsapi.amap.com/v1/track/terminal/trsearch',
        options: Options(
            headers: {'content-type': 'application/x-www-form-urlencoded'},
            method: 'POST'),
        data: {
          'key': amapTrackData['key'],
          'sid': amapTrackData['sid'],
          'tid': amapTrackData['tid'],
          'trid': trid,
          'page': 1,
          'pagesize': 999,
          'correction': correction,
          'recoup': 1,
          'gap': 50,
        });
    if (respone.data['errcode'] == 10000) {
      if (respone.data['data'] != null) {
        List tempList = [];
        for (Map item in respone.data['data']['tracks'][0]['points']) {
          List temp = item['location'].split(',');
          tempList.add({
            "lttd": temp[1],
            "lgtd": temp[0],
          });
        }
        return tempList;
      }
    }
    return null;
  }

  // 删除猎鹰轨迹
  amapDelTrack(String trid) async {
    // 删除猎鹰轨迹
    var respone = await dioMap.post(
        'https://tsapi.amap.com/v1/track/trace/delete',
        options: Options(
            headers: {'content-type': 'application/x-www-form-urlencoded'},
            method: 'POST'),
        data: {
          'key': amapTrackData['key'],
          'sid': amapTrackData['sid'],
          'tid': amapTrackData['tid'],
          'trid': trid,
        });
    if (respone.data['errcode'] == 10000) {}
  }
}
